//
// Created by liaoy on 2021/8/20.
//
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

typedef struct
{
    char *k;
    uint8_t v;
    uint8_t num_param[3];
} asm_table_t;

typedef struct
{
    uint16_t magic;
    uint16_t stack_size;
    uint32_t data_size;
    uint32_t startup;
} bytecode_header_t;

asm_table_t asm_table[90] = {
        {"EXIT",        0,    {0, 0,    0}},
        {"exit",        0,    {0, 0,    0}},
        {"INT_LOAD",    0x1,  {5, 0,    0}},
        {"int_load",    0x1,  {5, 0,    0}},
        {"INT2STR",     0x2,  {1, 0,    0}},
        {"int2str",     0x2,  {1, 0,    0}},

        {"JMP",         0x10, {4, 0,    0}},
        {"jmp",         0x10, {4, 0,    0}},
        {"JMP_Z",       0x11, {4, 0,    0}},
        {"jmp_z",       0x11, {4, 0,    0}},
        {"JMP_NZ",      0x12, {4, 0,    0}},
        {"jmp_nz",      0x12, {4, 0,    0}},

        {"XOR",         0x20, {3, 0,    0}},
        {"xor",         0x20, {3, 0,    0}},
        {"AND",         0x21, {3, 0,    0}},
        {"and",         0x21, {3, 0,    0}},
        {"OR",          0x22, {3, 0,    0}},
        {"or",          0x22, {3, 0,    0}},
        {"SHL",         0x23, {3, 0,    0}},
        {"shl",         0x23, {3, 0,    0}},
        {"SHR",         0x24, {3, 0,    0}},
        {"shl",         0x24, {3, 0,    0}},
        {"ADD",         0x25, {3, 0,    0}},
        {"add",         0x25, {3, 0,    0}},
        {"SUB",         0x26, {3, 0,    0}},
        {"sub",         0x26, {3, 0,    0}},
        {"MUL",         0x27, {3, 0,    0}},
        {"mul",         0x27, {3, 0,    0}},
        {"DIV",         0x28, {3, 0,    0}},
        {"div",         0x28, {3, 0,    0}},
        {"INC",         0x29, {3, 0,    0}},
        {"inc",         0x29, {3, 0,    0}},
        {"DEC",         0x2a, {3, 0,    0}},
        {"dec",         0x2a, {3, 0,    0}},
        {"MOD",         0x2b, {3, 0,    0}},
        {"mod",         0x2b, {3, 0,    0}},
        {"GE",          0x2c, {2, 0,    0}},
        {"ge",          0x2c, {2, 0,    0}},
        {"LE",          0x2d, {2, 0,    0}},
        {"le",          0x2d, {2, 0,    0}},
        {"NE",          0x2e, {2, 0,    0}},
        {"ne",          0x2e, {2, 0,    0}},

        {"STR_STORE",   0x30, {1, 0xff, 0}},
        {"str_store",   0x30, {1, 0xff, 0}},
        {"STR_CONCAT",  0x31, {3, 0,    0}},
        {"str_concat",  0x31, {3, 0,    0}},
        {"STR2INT",     0x32, {1, 0,    0}},
        {"str2int",     0x32, {1, 0,    0}},

        {"CMP_REG",     0x40, {2, 0,    0}},
        {"cmp_reg",     0x40, {2, 0,    0}},
        {"CMP_I",       0x41, {5, 0,    0}},
        {"cmp_i",       0x41, {5, 0,    0}},
        {"CMP_STR",     0x42, {1, 0xff, 0}},
        {"cmp_str",     0x42, {1, 0xff, 0}},
        {"IS_STR",      0x43, {1, 0,    0}},
        {"is_str",      0x43, {1, 0,    0}},
        {"IS_INT",      0x44, {1, 0,    0}},
        {"is_int",      0x44, {1, 0,    0}},

        {"NOP",         0x50, {0, 0,    0}},
        {"nop",         0x50, {0, 0,    0}},
        {"MV",          0x51, {2, 0,    0}},
        {"mv",          0x51, {2, 0,    0}},
        {"PRE_SYSCALL", 0x52, {1, 0,    0}},
        {"pre_syscall", 0x52, {1, 0,    0}},
        {"SYSCALL",     0x53, {3, 0,    0}},
        {"syscall",     0x53, {3, 0,    0}},

        {"PEEK",        0x60, {2, 0,    0}},
        {"peek",        0x60, {2, 0,    0}},
        {"POKE",        0x61, {2, 0,    0}},
        {"poke",        0x61, {2, 0,    0}},
        {"MEMCPY",      0x62, {3, 0,    0}},
        {"memcpy",      0x62, {3, 0,    0}},

        {"PUSH",        0x70, {1, 0,    0}},
        {"push",        0x70, {1, 0,    0}},
        {"PUSH_PTR",    0x71, {1, 0,    0}},
        {"push_ptr",    0x71, {1, 0,    0}},
        {"PUSH_STR",    0x72, {1, 0,    0}},
        {"push_str",    0x72, {1, 0,    0}},
        {"POP",         0x73, {1, 0,    0}},
        {"pop",         0x73, {1, 0,    0}},
        {"RET",         0x74, {0, 0,    0}},
        {"ret",         0x74, {0, 0,    0}},
        {"CALL",        0x75, {4, 0,    0}},
        {"call",        0x75, {4, 0,    0}},

        {"PTR_STORE",   0x80, {5, 0,    0}},
        {"ptr_store",   0x80, {5, 0,    0}},
        {"PTR2INT",     0x81, {3, 0,    0}},
        {"ptr2int",     0x81, {3, 0,    0}},
        {"IS_PTR",      0x82, {1, 0,    0}},
        {"is_ptr",      0x82, {1, 0,    0}},
};

typedef struct
{
    bytecode_header_t *head;
    uint8_t *code;
    uint32_t idx;
    uint32_t size;
} asm_bin_t;
asm_bin_t asm_bin;

int main(int argc, char **argv)
{
    uint8_t *_bin = malloc(1024 * 1);
    memset(_bin, 0, 1024 * 1);
    asm_bin.head = (bytecode_header_t *) _bin;
    asm_bin.code = _bin + sizeof(bytecode_header_t);
    asm_bin.size = sizeof(bytecode_header_t);
    asm_bin.idx = 0;
    if (argc != 2)
    {
        fprintf(stderr, "Parameter error!\n");
        return -1;
    }
    char *file_name = argv[1];
    struct stat file_state;
    if (stat(file_name, &file_state) != 0)
    {
        fprintf(stderr, "File %s is not found!\n", file_name);
        return -2;
    }

    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        fprintf(stderr, "Open description file fail!\n");
        return -3;
    }

    char str[1024];
    while (!feof(fp))
    {
        char *p_str = str;
        if (fgets(str, 1024, fp) != NULL)
        {
            for (int i = 0; i < 90; i++)
            {
                if (strcmp(asm_table[i].k, p_str) == 0)
                {

                }
            }
        }
    }

    return 0;
}